#include <string.h>
#include "AdminSerializer.h"

using namespace AgoraClient;

std::list<AdminSerializer::ChannelInfo*> *AdminSerializer::UnserializeChannelList(char *data, unsigned int& size)
{
	std::list<AdminSerializer::ChannelInfo*>* lst = new std::list<AdminSerializer::ChannelInfo*>();
	AdminSerializer::ChannelInfo *res;
	unsigned int nbchan = (*((int *)data));

	data += sizeof(int);
	size = (*((int *)data));
	data += sizeof(int);

	while (nbchan-- > 0)
	{
		data += sizeof(int);
		res = new AdminSerializer::ChannelInfo();
		res->name = std::string(data);
		data += res->name.length() + 1;
		res->maxNameLength = (*((int *)data));
		data += sizeof(int);
		res->maxPasswordLength = (*((int *)data));
		data += sizeof(int);
		res->motd = std::string(data);
		data += res->motd.length() + 1;
		res->maxMotdLength = (*((int *)data));
		data += sizeof(int);
		res->description = std::string(data);
		data += res->description.length() + 1;
		res->maxDescriptionLength = (*((int *)data));
		data += sizeof(int);
		res->visible = ((*((char *)data)) != 0);
		data ++;
		res->maxUser = (*((int *)data));
		data += sizeof(int);
		res->maxTalker = (*((int *)data));
		data += sizeof(int);
		res->id = (*((int *)data));
		data += sizeof(int);
		res->idParent = (*((int *)data));
		data += sizeof(int);
		res->hasPassword = ((*((char *)data)) != 0);
		data++;
		lst->push_back(res);
	}
	return lst;
}

void		AdminSerializer::SerializeChannel(const IChannel *chan, void *data, unsigned int& size)
{
	unsigned int tmp;
	size = sizeof(int) * 9 + 5 + chan->GetName().length() + chan->GetMotd().length() + chan->GetDescription().length();
	char *ptr = static_cast<char*>(data);

	tmp = size;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);
	memcpy(ptr++, chan->GetName().c_str(), chan->GetName().length() + 1);
	ptr += chan->GetName().length();
	tmp = chan->GetMaxNameLength();
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	tmp = chan->GetMaxPasswordLength();
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	memcpy(ptr++, chan->GetMotd().c_str(), chan->GetMotd().length() + 1);
	ptr += chan->GetMotd().length();
	tmp = chan->GetMaxMotdLength();
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	memcpy(ptr++, chan->GetDescription().c_str(), chan->GetDescription().length() + 1);
	ptr += chan->GetDescription().length();
	tmp = chan->GetMaxDescriptionLength();
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	char tmp2 = chan->GetVisibility() ? 1 : 0;
	memcpy(ptr++, &tmp2, 1);
	tmp = chan->GetMaxUser();
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);
	tmp = chan->GetMaxTalker();
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);
	tmp = chan->GetId();
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);
	tmp = chan->GetParent() ? chan->GetParent()->GetId() : 0;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);
	tmp2 = ((chan->GetPassword().length() > 0) ? 1 : 0);
	memcpy(ptr++, &tmp2, 1);
}

void*		AdminSerializer::SerializeChannelList(const std::map<unsigned int, IChannel *>& chanMap, unsigned int& size)
{
	unsigned int	tmp;
	char*			ptr;
	char*			data;

	size = 2 * sizeof(int);
	std::map<unsigned int, IChannel*>::const_iterator ittmp;

	std::map<unsigned int, IChannel*>::const_iterator it = chanMap.begin();
	std::map<unsigned int, IChannel*>::const_iterator itend = chanMap.end();

	ittmp = it;
	for(; ittmp != itend; ++ittmp)
	{
		size += sizeof(int) * 9 + 5 + (*ittmp).second->GetName().length() + (*ittmp).second->GetMotd().length() + (*ittmp).second->GetDescription().length();
	}

	data = new char[size];
	ptr = data;

	tmp = chanMap.size();
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);
	tmp = size;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	ittmp = it;
	for(; ittmp != itend; ++ittmp)
	{
		AdminSerializer::SerializeChannel((*ittmp).second, ptr, tmp);
		ptr += tmp;
	}
	return data;
}

AdminSerializer::ChannelInfo*	AdminSerializer::UnserializeChannelInfo(char *data, unsigned int& size)
{
	AdminSerializer::ChannelInfo* res = new AdminSerializer::ChannelInfo();


	res = new AdminSerializer::ChannelInfo();
	res->name = std::string(data);
	data += res->name.length() + 1;
	res->maxNameLength = (*((int *)data));
	data += sizeof(int);
	res->password = std::string(data);
	data += res->password.length() + 1;
	res->maxPasswordLength = (*((int *)data));
	data += sizeof(int);
	res->motd = std::string(data);
	data += res->motd.length() + 1;
	res->maxMotdLength = (*((int *)data));
	data += sizeof(int);
	res->description = std::string(data);
	data += res->description.length() + 1;
	res->maxDescriptionLength = (*((int *)data));
	data += sizeof(int);
	res->visible = ((*((char *)data)) != 0);
	data ++;
	res->maxUser = (*((int *)data));
	data += sizeof(int);
	res->maxTalker = (*((int *)data));
	data += sizeof(int);
	res->idParent = (*((int *)data));
	data += sizeof(int);
	res->hasPassword = ((*((char *)data)) != 0);
	data++;
	return res;
}

void*	AdminSerializer::SerializeChannelInfo(ChannelInfo& chanInfo, unsigned int& size)
{
	size = sizeof(int) * 8 + 6 + chanInfo.password.length() + chanInfo.name.length() + chanInfo.motd.length() + chanInfo.description.length();
	char *data = new char[size];
	unsigned int tmp;
	char *ptr = data;


	memcpy(ptr++, chanInfo.name.c_str(), chanInfo.name.length() + 1);
	ptr += chanInfo.name.length();
	tmp = chanInfo.maxNameLength;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	memcpy(ptr++, chanInfo.password.c_str(), chanInfo.password.length() + 1);
	ptr += chanInfo.password.length();
	tmp = chanInfo.maxPasswordLength;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	memcpy(ptr++, chanInfo.motd.c_str(), chanInfo.motd.length() + 1);
	ptr += chanInfo.motd.length();
	tmp = chanInfo.maxMotdLength;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	memcpy(ptr++, chanInfo.description.c_str(), chanInfo.description.length() + 1);
	ptr += chanInfo.description.length();
	tmp = chanInfo.maxDescriptionLength;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	char tmp2 = chanInfo.visible ? 1 : 0;
	memcpy(ptr++, &tmp2, 1);
	tmp = chanInfo.maxUser;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);
	tmp = chanInfo.maxTalker;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);
	tmp = chanInfo.idParent;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);
	tmp2 = chanInfo.hasPassword ? 1 : 0;
	memcpy(ptr++, &tmp2, 1);

	return data;
}

std::list<AdminSerializer::UserInfo*>*	AdminSerializer::UnserializeUserList(char* data, unsigned int& size)
{
	std::list<AdminSerializer::UserInfo*>* lst = new std::list<AdminSerializer::UserInfo*>();
	AdminSerializer::UserInfo *res;
	unsigned int nbuser = (*((int *)data));

	data += sizeof(int);
	size = (*((int *)data));
	data += sizeof(int);

	while (nbuser-- > 0)
	{
		data += sizeof(int);
		res = new AdminSerializer::UserInfo();
		res->id = (*((int *)data));
		data += sizeof(int);
		res->login = std::string(data);
		data += res->login.length() + 1;
		res->idCurrentChannel = (*((int *)data));
		data += sizeof(int);
		res->connected = (*((bool*)data));
		data += sizeof(bool);
		lst->push_back(res);
	}
	return lst;
}

AdminSerializer::UserInfo*	AdminSerializer::UnserializeUserInfo(char* data, unsigned int& size)
{
	AdminSerializer::UserInfo* res = new AdminSerializer::UserInfo();

	res = new AdminSerializer::UserInfo();
	res->id = (*((int *)data));
	data += sizeof(int);
	res->login = std::string(data);
	data += res->login.length() + 1;
	res->idCurrentChannel = (*((int *)data));
	data += sizeof(int);
	res->connected = (*(bool*)data);
	data += sizeof(bool);

	return res;
}

void*	AdminSerializer::SerializeUserInfo(UserInfo& userInfo, unsigned int& size)
{
	size = sizeof(int) * 2 + 1 + userInfo.login.length() + sizeof(bool);
	char *data = new char[size];
	unsigned int tmp;
	char *ptr = data;

	tmp = userInfo.id;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	memcpy(ptr++, userInfo.login.c_str(), userInfo.login.length() + 1);
	ptr += userInfo.login.length();

	tmp = userInfo.idCurrentChannel;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	tmp = userInfo.connected;
	memcpy(ptr, &tmp, sizeof(bool));
	ptr += sizeof(bool);

	return data;
}

void*	AdminSerializer::SerializeUserList(const std::map<unsigned int, IUser*>& userMap, unsigned int& size)
{
	unsigned int	tmp;
	char*			ptr;
	char*			data;

	size = 2 * sizeof(int);
	std::map<unsigned int, IUser*>::const_iterator ittmp;

	std::map<unsigned int, IUser*>::const_iterator it = userMap.begin();
	std::map<unsigned int, IUser*>::const_iterator itend = userMap.end();

	ittmp = it;
	for(; ittmp != itend; ++ittmp)
	{
		size += sizeof(int) * 3 + 1 + (*ittmp).second->GetLogin().length() + sizeof(bool);
	}

	data = new char[size];
	ptr = data;

	tmp = userMap.size();
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);
	tmp = size;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	ittmp = it;
	for(; ittmp != itend; ++ittmp)
	{
		AdminSerializer::SerializeUser((*ittmp).second, ptr, tmp);
		ptr += tmp;
	}
	return data;
}

void	AdminSerializer::SerializeUser(const IUser* user, void* data, unsigned int& size)
{
	unsigned int tmp;
	size = sizeof(int) * 3 + 1 + user->GetLogin().length() + sizeof(bool);
	char *ptr = static_cast<char*>(data);

	tmp = size;
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	tmp = user->GetId();
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	memcpy(ptr++, user->GetLogin().c_str(), user->GetLogin().length() + 1);
	ptr += user->GetLogin().length();

	tmp = user->GetCurrentChannelId();
	memcpy(ptr, &tmp, sizeof(int));
	ptr += sizeof(int);

	tmp = user->IsConnected();
	memcpy(ptr, &tmp, sizeof(bool));
	ptr += sizeof(bool);

}


void*	AdminSerializer::SerializeHostRight(const IHostRight *rights, unsigned int& size)
{
	char *data = new char[9];
	size = 9;

	data[0] = rights->GetCanChangeLogin() ? 1 : 0;
	data[1] = rights->GetCanChangePassword() ? 1 : 0;
	data[2] = rights->GetCanChangeChannel() ? 1 : 0;
	data[3] = rights->GetCanCreateChannel() ? 1 : 0;
	data[4] = rights->GetCanDeleteChannel() ? 1 : 0;
	data[5] = rights->GetCanMoveChannel() ? 1 : 0;
	data[6] = rights->GetCanKickUser() ? 1 : 0;
	data[7] = rights->GetCanBanUser() ? 1 : 0;
	data[8] = rights->GetCanEditUser() ? 1 : 0;

	return	data;
}

AdminSerializer::HostRightInfo*	AdminSerializer::UnserializeHostRight(char *data, unsigned int& size)
{
	AdminSerializer::HostRightInfo *info = new AdminSerializer::HostRightInfo();

	info->canChangeLogin = (data[0] == 1);
	info->canChangePassword = (data[1] == 1);
	info->canChangeChannel = (data[2] == 1);
	info->canCreateChannel = (data[3] == 1);
	info->canDeleteChannel = (data[4] == 1);
	info->canMoveChannel = (data[5] == 1);
	info->canKickUser = (data[6] == 1);
	info->canBanUser = (data[7] == 1);
	info->canEditUser = (data[8] == 1);

	return info;
}

void*	AdminSerializer::SerializeHostRightInfo(const HostRightInfo* info, unsigned int& size)
{
	char *data = new char[9];
	size = 9;

	data[0] = info->canChangeLogin ? 1 : 0;
	data[1] = info->canChangePassword ? 1 : 0;
	data[2] = info->canChangeChannel ? 1 : 0;
	data[3] = info->canCreateChannel ? 1 : 0;
	data[4] = info->canDeleteChannel ? 1 : 0;
	data[5] = info->canMoveChannel ? 1 : 0;
	data[6] = info->canKickUser ? 1 : 0;
	data[7] = info->canBanUser ? 1 : 0;
	data[8] = info->canEditUser ? 1 : 0;

	return	data;
}

void*						AdminSerializer::SerializeChannelRight(const IChannelRight *rights, unsigned int& size)
{
	char *data = new char[8];
	size = 8;

	data[0] = rights->GetCanCreateChannelChild() ? 1 : 0;
	data[1] = rights->GetCanDeleteChannelChild() ? 1 : 0;
	data[2] = rights->GetCanEditChannel() ? 1 : 0;
	data[3] = rights->GetCanEditUserRight() ? 1 : 0;
	data[4] = rights->GetCanTalkChannel() ? 1 : 0;
	data[5] = rights->GetCanWriteChannel() ? 1 : 0;
	data[6] = rights->GetCanKickUser() ? 1 : 0;
	data[7] = rights->GetCanBanUser() ? 1 : 0;

	return data;
}

AdminSerializer::ChannelRightInfo*			AdminSerializer::UnserializeChannelRight(char *data, unsigned int& size)
{
	AdminSerializer::ChannelRightInfo* info = new AdminSerializer::ChannelRightInfo();

	info->canCreate = (data[0] == 1);
	info->canDelete = (data[1] == 1);
	info->canEdit = (data[2] == 1);
	info->canEditUser = (data[3] == 1);
	info->canTalk = (data[4] == 1);
	info->canWrite = (data[5] == 1);
	info->canKick = (data[6] == 1);
	info->canBan = (data[7] == 1);

	return info;
}

void*						AdminSerializer::SerializeHostChannelInfo(const ChannelRightInfo* info, unsigned int& size)
{
	char *data = new char[8];
	size = 8;

	data[0] = info->canCreate ? 1 : 0;
	data[1] = info->canDelete ? 1 : 0;
	data[2] = info->canEdit ? 1 : 0;
	data[3] = info->canEditUser ? 1 : 0;
	data[4] = info->canTalk ? 1 : 0;
	data[5] = info->canWrite ? 1 : 0;
	data[6] = info->canKick ? 1 : 0;
	data[7] = info->canBan ? 1 : 0;

	return data;
}

